from time import time as now

from zope.interface import implements
from zope.interface import Interface

from twisted.web import xmlrpc
from twisted.python.components import registerAdapter

from nevow import url
from nevow import rend
from nevow import static
from nevow import inevow
from nevow import loaders
from nevow import tags as t

import formal
from formal import widget

import const
import utils
from axiomstore import WikiPost
from iwiki import IWiki
from iwiki import IStore
from iwiki import ITimer

categories = [ (x, x) for x in const.categories ]
hidden = formal.widgetFactory(widget.Hidden)
cats = formal.widgetFactory(widget.SelectChoice, categories)
textarea = formal.widgetFactory(widget.TextArea)

def pptime(tt):
    return tt.asHumanly()+" UTC"

def atompptime(tt):
    return tt.asISO8601TimeAndDate()

class ITimer(Interface):
    pass

class BaseUI(rend.Page):
    addSlash = True
    def renderHTTP(self, ctx):
        return IStore(ctx).transact(rend.Page.renderHTTP, self, ctx)
        
    def locateChild(self, ctx, segments):
        page = segments[-1]
        if IWiki(IStore(ctx)).isMakePage(page):
            path = '/'.join(segments)
            wikiWord = segments[-1]
            segments = segments[:-1] + ('insertEntry',)
            # we have to do this request wrangling in order to support virtual
            # hosts
            req = inevow.IRequest(ctx)
            req.path = '/%s' % '/'.join(segments)
            req.uri = '%s?%s' % (req.path, wikiWord)
            req.postpath = list(segments)
        return IStore(ctx).transact(rend.Page.locateChild, self, ctx, segments)

class HomePage(BaseUI):
    
    docFactory = loaders.xmlfile(const.homeTemplate)
    child_styles = static.File(const.staticDir+'/styles')
    child_images = static.File(const.staticDir+'/images')
    child_js = static.File(const.staticDir+'/js')
    child_formal_css = formal.defaultCSS

    def render_starttimer(self, ctx, data):
        ctx.remember(now(), ITimer)
        return ctx.tag
        
    def render_stoptimer(self, ctx, data):
        start = ITimer(ctx)
        return ctx.tag['%s' % (now()-start)]

    def render_needForms(self, ctx, data):
        action = ctx.arg('action', 'view')
        if action == 'edit':
            form = inevow.IQ(ctx).onePattern('frm')
            return ctx.tag[form]
        return ctx.tag.clear()

    def data_getEntries(self, ctx, data):
        num = ctx.arg('num', '60')
        try:
            id = self.original.id
        except AttributeError:
            id = const.homePage
        return [ IWiki(IStore(ctx)).getPage(id) ]

    def data_getCategories(self, ctx, data):
        return IWiki(IStore(ctx)).getCategories()

    def data_getExistingWikiPages(self, ctx, data):
        return IWiki(IStore(ctx)).getExistingWikiPages()

    def data_getPendingWikiPages(self, ctx, data):
        return IWiki(IStore(ctx)).getPendingWikiPages()

    def render_entries(self, ctx, data):
        ctx.tag.fillSlots('modification', pptime(data.modified))
        ctx.tag.fillSlots('category', data.category)
        ctx.tag.fillSlots('author', data.author)
        ctx.tag.fillSlots('title', data.title)
        ctx.tag.fillSlots('content', t.xml(utils.parseWikiWords(
            store=IStore(ctx), content=data.content)))
        ctx.tag.fillSlots('permaLink', url.root.child('%s' % (data.id)))
        return ctx.tag

    #def render_insert(self, ctx, data):
    #    return ctx.tag

    def render_editer(self, ctx, data):
        ctx.tag.fillSlots('editPost', url.root.child('%s' % (data.id)
                                                         ).add('action','edit'))
        return ctx.tag

    def render_insert(self, ctx, data):
        ctx.tag.fillSlots('insert', url.root.child('insertEntry'))
        return ctx.tag

    def child_insertEntry(self, ctx):
        return NewEntry()

    def child_byCategory(self, ctx):
        return ByCategory()

    def childFactory(self, ctx, segment):
        if not segment:
            segment = utils.frontPageName()
        return IWiki(IStore(ctx)).getPage(segment)

class NewEntry(formal.ResourceMixin, BaseUI):

    implements(inevow.IResource)

    docFactory = loaders.xmlfile(const.insertTemplate)

    def submitEntry(self, ctx, form, data):
        title = data['Title']
        id = data['Id']
        if not id:
            id = utils.makeWikiWord(title)
        newPost = WikiPost(store=IStore(ctx),
            id=unicode(id),
            author=unicode(data['Author']),
            title=unicode(title),
            category=unicode(data['Category']),
            content=data['Content'])
        IWiki(IStore(ctx)).updatePost(newPost)
        print "Redirecting to /"+id
        return url.here.click("/%s" % id)

    def form_newEntry(self, ctx):
        id = inevow.IRequest(ctx).URLPath().query
        form = formal.Form()
        form.addField('Id', formal.String(), hidden)
        form.addField('Title', formal.String(required=True))
        form.addField('Author', formal.String())
        form.addField('Category', formal.String(), cats)
        form.addField('Content', formal.String(required=True), textarea)
        form.addAction(self.submitEntry)
        form.data = {
            'Id': id,
            'Title': id,
            'Author': 'Anonymous Prairie Dog',
            }
        return form

class Entry(formal.ResourceMixin, HomePage):

    def data_getEntries(self, ctx, data):
        return [data]

    def submitEntry(self, ctx, form, data):
        title = data['Title']
        id = data['Id']
        if not id:
            id = utils.makeWikiWord(title)
        post = IStore(ctx).findOrCreate(WikiPost, id=unicode(id))
        post.author = unicode(data['Author'])
        post.title = unicode(title)
        post.category = unicode(data['Category'])
        post.content = data['Content']
        IWiki(IStore(ctx)).updatePost(post)
        print "Redirecting to /"+id
        return url.here.click("/%s" % id)

    def form_editEntry(self, ctx):
        print "Editing Entry..."
        form = formal.Form()
        form.addField('Id', formal.String(), hidden)
        form.addField('Title', formal.String(required=True))
        form.addField('Author', formal.String())
        form.addField('Category', formal.String(), cats)
        form.addField('Content', formal.String(required=True), textarea)
        form.addAction(self.submitEntry)
        form.data = {
            'Id': self.original.id,
            'Title': self.original.title,
            'Author': self.original.author,
            'Category': self.original.category,
            'Content': self.original.content,
            }
        return form

class ByCategory(HomePage):

    implements(inevow.IResource)

    docFactory = loaders.xmlfile(const.catsTemplate)

    def locateChild(self, ctx, segments):
        return self, ()
        
    def data_getEntries(self, ctx, data):
        req = inevow.IRequest(ctx)
        cat = req.path.strip('/').split('/')[-1]
        print "got category: %s" % cat
        entries = IWiki(IStore(ctx)).getPostsByCategory(cat)
        print "data length: %s" % len(list(entries))
        return entries

    def render_entries(self, ctx, data):
        ctx.tag.fillSlots('modification', pptime(data.modified))
        ctx.tag.fillSlots('author', data.author)
        ctx.tag.fillSlots('title', data.title)
        ctx.tag.fillSlots('permaLink', url.root.child('%s' % (data.id)))
        return ctx.tag

registerAdapter(Entry, WikiPost, inevow.IResource)

